package com.itec.learn.java.abc.condition;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 有三个线程分别打印A、B、C,请用多线程编程实现，在屏幕上循环打印10次ABCABC…
 * @author chenyiqun
 */
public class ConditionExample {

    private Lock lock = new ReentrantLock();
    private Condition conditionA = lock.newCondition();
    private Condition conditionB = lock.newCondition();
    private Condition conditionC = lock.newCondition();

    private String currentThreadName = "A";

    public static void main(String[] args) {
        ConditionExample example = new ConditionExample();
        ExecutorService service = Executors.newFixedThreadPool(3);
        service.execute(example.new ThreadA());
        service.execute(example.new ThreadB());
        service.execute(example.new ThreadC());
        service.shutdown();
    }

    private class ThreadA implements Runnable{
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                lock.lock();
                try {
                    while (!currentThreadName.equals("A")){
                        try {
                            conditionA.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("A");
                    currentThreadName="B";
                    conditionB.signal();
                } finally {
                    lock.unlock();
                }
            }
        }
    }

    private class ThreadB implements Runnable{
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                lock.lock();
                try {
                    while (!currentThreadName.equals("B")){
                        try {
                            conditionB.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("B");
                    currentThreadName="C";
                    conditionC.signal();
                } finally {
                    lock.unlock();
                }
            }
        }
    }

    private class ThreadC implements Runnable{
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                lock.lock();
                try {
                    while (!currentThreadName.equals("C")){
                        try {
                            conditionC.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("C");
                    currentThreadName="A";
                    conditionA.signal();
                } finally {
                    lock.unlock();
                }
            }
        }
    }


}
